# -*- coding: utf-8 -*-

"""有8瓶水，其中有1瓶有毒，用3只老鼠一次检测出哪瓶有毒？

--------------------------Ⅰ--------------------------
试想，换个问法，有8瓶水，其中一瓶有毒，那么最少可以用几只老鼠一次检测出哪瓶有毒？
很显然每只老鼠需要组合着喝水，并且根据老鼠试药之后不同的结果来判断哪瓶水有毒。

那么韦恩图就是一个比较好的解决方案。一个圈代表一只老鼠，各个圈组成的各个区域，每个区域放一瓶药水，每只老鼠喝自己圈起来的药水组合。每个老鼠喝水的组合对称。
任何一个区域的药水有毒，都会导致老鼠的死亡存活情况不一样。
二维平面画对称韦恩图[https://bioinfogp.cnb.csic.es/tools/venny/index.html]，注意，圈外自然形成一个全排斥区域

1个圈只能形成 1+1 2个区域
2个圈只能形成 3+1 4个区域
3个圈只能形成 7+1 8个区域
4个圈只能形成 15+1 16个区域
...
类推
4个圈只能形成 2**n 个区域

要形成8个区域，那么在对称韦恩图中，至少需要3个圈
这就解决了需要几瓶的问题

--------------------------Ⅱ--------------------------
下面解决是哪瓶的问题（将韦恩图用到计算机表示）
根据韦恩图中不同药水及老鼠的编号，老鼠试毒情况如下：
药水编号：1    2    3    4    5    6    7    8(圈外)
老鼠Ａ喝：Y              Y    Y         Y
老鼠Ｂ喝：     Y              Y    Y    Y
老鼠Ｃ喝：          Y    Y         Y    Y

推导几类情况（韦恩图更好判断）：
1）三只老鼠都没有死，那么肯定是圈外第8瓶水有毒
2）只有一只老鼠死了（如A），那么第1瓶有毒
3）有两只老鼠死了（如AB），那么第4瓶有毒
4）三只老鼠都死了，那么第7瓶有毒

--------------------------Ⅲ--------------------------
按道理，现在就已经能算出哪瓶水有毒了，不过我们稍微调整一下药水排布的顺序，可以发现与1-7这7个数字的二进制表示一致
药水编号：3    2    6    1    4    5    7    8(圈外)
老鼠Ａ喝：               Y    Y    Y    Y
老鼠Ｂ喝：     Y    Y              Y    Y
老鼠Ｃ喝：Y         Y         Y         Y

 　　　数字：1    2    3    4    5    6    7
二进制(2位)：0    0    0    1    1    1    1
二进制(1位)：0    1    1    0    0    1    1
二进制(0位)：1    0    1    0    1    0    1

这样为每瓶水编上数值，计算出各自二进制
第一只老鼠喝第一行标记为1的组合水，
. 二 ....... 二 ..... 1 .......
. 三 ....... 三 ..... 1 .......
很方便就用计算机的方式实现老鼠的喝水组合，基于韦恩图，实现于二进制编码

--------------------------Ⅳ--------------------------
推广：用二进制解法适合 (n, less(2**n), 1)的问题，如用<10>只老鼠从<1000(less(2**10=1024))>瓶水里面检测出(1)瓶有毒

！！！有两瓶有毒的情况不能一次检测完成，如8瓶水2瓶有毒，用6只老鼠一次检测？至今我还未解出方案

已经找到解法，还是利用的对称思想，碰到一个答案
等边三角形及三条中线，对应6只老鼠，7个点对应7瓶药水，另外留1瓶不加以测试

        1
      / | \
     /  |  \
    4   |   5
   /  \ | /  \
  /     7     \
 /   /  |  \   \
2-------6-------3

8

1: 142
2: 153
3: 263
4: 176
5: 275
6: 374

没有一个中心，形成一瓶药水有毒，全部老鼠死亡，另一瓶药水无从下手的场景
若7、1有毒，那么喝263的老鼠还会存活
若7，5有毒，那么喝142，263的老鼠还会存活
若1，2有毒，那么喝374的老鼠会存活
若4，5有毒，那么喝176，263的老鼠会存活
...
"""

def test(waters=8, mice='111'):
    waters = [bin(i)[2:].zfill(3) for i in range(waters)]
    
    poison = ''
    for mouse in mice:
        if int(mouse):
            poison += '1'
        else:
            poison += '0'
    
    return poison

if __name__ == '__main__':
    print(test())
